/*
 * Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
 * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
 */

// This file was generated automatically. See compiler/ir/ir.tree/tree-generator/ReadMe.md.
// DO NOT MODIFY IT MANUALLY.

package org.jetbrains.kotlin.ir.util

import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.IrSimpleType
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.IrTypeProjection
import org.jetbrains.kotlin.ir.visitors.IrVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid

/**
 * Auto-generated by [org.jetbrains.kotlin.ir.generator.print.IrTreeSymbolsVisitorPrinter]
 */
open class IrTreeSymbolsVisitor(
    private val symbolVisitor: SymbolVisitor,
) : IrVisitorVoid() {

    open fun visitType(container: IrElement, type: IrType) {}

    open fun visitTypeRecursively(container: IrElement, type: IrType) {
        visitType(container, type)
        if (type is IrSimpleType) {
            type.arguments.forEach {
                if (it is IrTypeProjection) {
                    visitTypeRecursively(container, it.type)
                }
            }
        }
    }

    override fun visitElement(element: IrElement) {
        element.acceptChildrenVoid(this)
    }

    override fun visitDeclaration(declaration: IrDeclarationBase) {
        visitElement(declaration)
    }

    override fun visitValueParameter(declaration: IrValueParameter) {
        symbolVisitor.visitDeclaredValueParameter(declaration.symbol)
        declaration.varargElementType?.let { visitTypeRecursively(declaration, it) }
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitClass(declaration: IrClass) {
        symbolVisitor.visitDeclaredClass(declaration.symbol)
        declaration.sealedSubclasses.forEach { symbolVisitor.visitReferencedClass(it) }
        declaration.valueClassRepresentation?.mapUnderlyingType {
            visitTypeRecursively(declaration, it)
            it
        }
        declaration.superTypes.forEach { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
        symbolVisitor.visitDeclaredAnonymousInitializer(declaration.symbol)
        visitDeclaration(declaration)
    }

    override fun visitTypeParameter(declaration: IrTypeParameter) {
        symbolVisitor.visitDeclaredTypeParameter(declaration.symbol)
        declaration.superTypes.forEach { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitFunction(declaration: IrFunction) {
        visitTypeRecursively(declaration, declaration.returnType)
        visitDeclaration(declaration)
    }

    override fun visitConstructor(declaration: IrConstructor) {
        symbolVisitor.visitDeclaredConstructor(declaration.symbol)
        visitFunction(declaration)
    }

    override fun visitEnumEntry(declaration: IrEnumEntry) {
        symbolVisitor.visitDeclaredEnumEntry(declaration.symbol)
        visitDeclaration(declaration)
    }

    override fun visitField(declaration: IrField) {
        symbolVisitor.visitDeclaredField(declaration.symbol)
        declaration.correspondingPropertySymbol?.let(symbolVisitor::visitReferencedProperty)
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty) {
        symbolVisitor.visitDeclaredLocalDelegatedProperty(declaration.symbol)
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitModuleFragment(declaration: IrModuleFragment) {
        visitElement(declaration)
    }

    override fun visitProperty(declaration: IrProperty) {
        symbolVisitor.visitDeclaredProperty(declaration.symbol)
        declaration.overriddenSymbols.forEach { symbolVisitor.visitReferencedProperty(it) }
        visitDeclaration(declaration)
    }

    override fun visitScript(declaration: IrScript) {
        symbolVisitor.visitDeclaredScript(declaration.symbol)
        declaration.providedProperties.forEach { symbolVisitor.visitReferencedProperty(it) }
        declaration.resultProperty?.let(symbolVisitor::visitReferencedProperty)
        declaration.importedScripts?.forEach { symbolVisitor.visitReferencedScript(it) }
        declaration.earlierScripts?.forEach { symbolVisitor.visitReferencedScript(it) }
        declaration.targetClass?.let(symbolVisitor::visitReferencedClass)
        declaration.baseClass?.let { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitReplSnippet(declaration: IrReplSnippet) {
        symbolVisitor.visitDeclaredReplSnippet(declaration.symbol)
        declaration.stateObject?.let(symbolVisitor::visitReferencedClass)
        declaration.targetClass?.let(symbolVisitor::visitReferencedClass)
        declaration.returnType?.let { visitTypeRecursively(declaration, it) }
        visitDeclaration(declaration)
    }

    override fun visitSimpleFunction(declaration: IrSimpleFunction) {
        symbolVisitor.visitDeclaredSimpleFunction(declaration.symbol)
        declaration.overriddenSymbols.forEach { symbolVisitor.visitReferencedSimpleFunction(it) }
        declaration.correspondingPropertySymbol?.let(symbolVisitor::visitReferencedProperty)
        visitFunction(declaration)
    }

    override fun visitTypeAlias(declaration: IrTypeAlias) {
        symbolVisitor.visitDeclaredTypeAlias(declaration.symbol)
        visitTypeRecursively(declaration, declaration.expandedType)
        visitDeclaration(declaration)
    }

    override fun visitVariable(declaration: IrVariable) {
        symbolVisitor.visitDeclaredVariable(declaration.symbol)
        visitTypeRecursively(declaration, declaration.type)
        visitDeclaration(declaration)
    }

    override fun visitPackageFragment(declaration: IrPackageFragment) {
        visitElement(declaration)
    }

    override fun visitExternalPackageFragment(declaration: IrExternalPackageFragment) {
        symbolVisitor.visitDeclaredExternalPackageFragment(declaration.symbol)
        visitPackageFragment(declaration)
    }

    override fun visitFile(declaration: IrFile) {
        symbolVisitor.visitDeclaredFile(declaration.symbol)
        visitPackageFragment(declaration)
    }

    override fun visitExpression(expression: IrExpression) {
        visitTypeRecursively(expression, expression.type)
        visitElement(expression)
    }

    override fun visitBody(body: IrBody) {
        visitElement(body)
    }

    override fun visitExpressionBody(body: IrExpressionBody) {
        visitBody(body)
    }

    override fun visitBlockBody(body: IrBlockBody) {
        visitBody(body)
    }

    override fun visitDeclarationReference(expression: IrDeclarationReference) {
        visitExpression(expression)
    }

    override fun visitMemberAccess(expression: IrMemberAccessExpression<*>) {
        for (type in expression.typeArguments) {
            if (type != null) {
                visitTypeRecursively(expression, type)
            }
        }
        visitDeclarationReference(expression)
    }

    override fun visitFunctionAccess(expression: IrFunctionAccessExpression) {
        visitMemberAccess(expression)
    }

    override fun visitConstructorCall(expression: IrConstructorCall) {
        symbolVisitor.visitReferencedConstructor(expression.symbol)
        visitFunctionAccess(expression)
    }

    override fun visitSingletonReference(expression: IrGetSingletonValue) {
        visitDeclarationReference(expression)
    }

    override fun visitGetObjectValue(expression: IrGetObjectValue) {
        symbolVisitor.visitReferencedClass(expression.symbol)
        visitSingletonReference(expression)
    }

    override fun visitGetEnumValue(expression: IrGetEnumValue) {
        symbolVisitor.visitReferencedEnumEntry(expression.symbol)
        visitSingletonReference(expression)
    }

    override fun visitRawFunctionReference(expression: IrRawFunctionReference) {
        symbolVisitor.visitReferencedFunction(expression.symbol)
        visitDeclarationReference(expression)
    }

    override fun visitContainerExpression(expression: IrContainerExpression) {
        visitExpression(expression)
    }

    override fun visitBlock(expression: IrBlock) {
        visitContainerExpression(expression)
    }

    override fun visitComposite(expression: IrComposite) {
        visitContainerExpression(expression)
    }

    override fun visitReturnableBlock(expression: IrReturnableBlock) {
        symbolVisitor.visitDeclaredReturnableBlock(expression.symbol)
        visitBlock(expression)
    }

    override fun visitInlinedFunctionBlock(inlinedBlock: IrInlinedFunctionBlock) {
        inlinedBlock.inlinedFunctionSymbol?.let(symbolVisitor::visitReferencedFunction)
        visitBlock(inlinedBlock)
    }

    override fun visitSyntheticBody(body: IrSyntheticBody) {
        visitBody(body)
    }

    override fun visitBreakContinue(jump: IrBreakContinue) {
        visitExpression(jump)
    }

    override fun visitBreak(jump: IrBreak) {
        visitBreakContinue(jump)
    }

    override fun visitContinue(jump: IrContinue) {
        visitBreakContinue(jump)
    }

    override fun visitCall(expression: IrCall) {
        symbolVisitor.visitReferencedSimpleFunction(expression.symbol)
        expression.superQualifierSymbol?.let(symbolVisitor::visitReferencedClass)
        visitFunctionAccess(expression)
    }

    override fun visitCallableReference(expression: IrCallableReference<*>) {
        visitMemberAccess(expression)
    }

    override fun visitFunctionReference(expression: IrFunctionReference) {
        expression.reflectionTarget?.let(symbolVisitor::visitReferencedFunction)
        visitCallableReference(expression)
    }

    override fun visitPropertyReference(expression: IrPropertyReference) {
        expression.field?.let(symbolVisitor::visitReferencedField)
        expression.getter?.let(symbolVisitor::visitReferencedSimpleFunction)
        expression.setter?.let(symbolVisitor::visitReferencedSimpleFunction)
        visitCallableReference(expression)
    }

    override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference) {
        symbolVisitor.visitReferencedVariable(expression.delegate)
        symbolVisitor.visitReferencedSimpleFunction(expression.getter)
        expression.setter?.let(symbolVisitor::visitReferencedSimpleFunction)
        visitCallableReference(expression)
    }

    override fun visitRichCallableReference(expression: IrRichCallableReference<*>) {
        visitExpression(expression)
    }

    override fun visitRichFunctionReference(expression: IrRichFunctionReference) {
        symbolVisitor.visitReferencedSimpleFunction(expression.overriddenFunctionSymbol)
        visitRichCallableReference(expression)
    }

    override fun visitRichPropertyReference(expression: IrRichPropertyReference) {
        visitRichCallableReference(expression)
    }

    override fun visitClassReference(expression: IrClassReference) {
        symbolVisitor.visitReferencedClassifier(expression.symbol)
        visitTypeRecursively(expression, expression.classType)
        visitDeclarationReference(expression)
    }

    override fun visitConst(expression: IrConst) {
        visitExpression(expression)
    }

    override fun visitConstantValue(expression: IrConstantValue) {
        visitExpression(expression)
    }

    override fun visitConstantPrimitive(expression: IrConstantPrimitive) {
        visitConstantValue(expression)
    }

    override fun visitConstantObject(expression: IrConstantObject) {
        symbolVisitor.visitReferencedConstructor(expression.constructor)
        expression.typeArguments.forEach { visitTypeRecursively(expression, it) }
        visitConstantValue(expression)
    }

    override fun visitConstantArray(expression: IrConstantArray) {
        visitConstantValue(expression)
    }

    override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
        symbolVisitor.visitReferencedConstructor(expression.symbol)
        visitFunctionAccess(expression)
    }

    override fun visitDynamicExpression(expression: IrDynamicExpression) {
        visitExpression(expression)
    }

    override fun visitDynamicOperatorExpression(expression: IrDynamicOperatorExpression) {
        visitDynamicExpression(expression)
    }

    override fun visitDynamicMemberExpression(expression: IrDynamicMemberExpression) {
        visitDynamicExpression(expression)
    }

    override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) {
        symbolVisitor.visitReferencedConstructor(expression.symbol)
        visitFunctionAccess(expression)
    }

    override fun visitErrorExpression(expression: IrErrorExpression) {
        visitExpression(expression)
    }

    override fun visitErrorCallExpression(expression: IrErrorCallExpression) {
        visitErrorExpression(expression)
    }

    override fun visitFieldAccess(expression: IrFieldAccessExpression) {
        visitDeclarationReference(expression)
    }

    override fun visitGetField(expression: IrGetField) {
        visitFieldAccess(expression)
    }

    override fun visitSetField(expression: IrSetField) {
        visitFieldAccess(expression)
    }

    override fun visitFunctionExpression(expression: IrFunctionExpression) {
        visitExpression(expression)
    }

    override fun visitGetClass(expression: IrGetClass) {
        visitExpression(expression)
    }

    override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall) {
        symbolVisitor.visitReferencedClass(expression.classSymbol)
        visitExpression(expression)
    }

    override fun visitLoop(loop: IrLoop) {
        visitExpression(loop)
    }

    override fun visitWhileLoop(loop: IrWhileLoop) {
        visitLoop(loop)
    }

    override fun visitDoWhileLoop(loop: IrDoWhileLoop) {
        visitLoop(loop)
    }

    override fun visitReturn(expression: IrReturn) {
        symbolVisitor.visitReferencedReturnTarget(expression.returnTargetSymbol)
        visitExpression(expression)
    }

    override fun visitStringConcatenation(expression: IrStringConcatenation) {
        visitExpression(expression)
    }

    override fun visitSuspensionPoint(expression: IrSuspensionPoint) {
        visitExpression(expression)
    }

    override fun visitSuspendableExpression(expression: IrSuspendableExpression) {
        visitExpression(expression)
    }

    override fun visitThrow(expression: IrThrow) {
        visitExpression(expression)
    }

    override fun visitTry(aTry: IrTry) {
        visitExpression(aTry)
    }

    override fun visitCatch(aCatch: IrCatch) {
        visitElement(aCatch)
    }

    override fun visitTypeOperator(expression: IrTypeOperatorCall) {
        visitTypeRecursively(expression, expression.typeOperand)
        visitExpression(expression)
    }

    override fun visitValueAccess(expression: IrValueAccessExpression) {
        visitDeclarationReference(expression)
    }

    override fun visitGetValue(expression: IrGetValue) {
        visitValueAccess(expression)
    }

    override fun visitSetValue(expression: IrSetValue) {
        visitValueAccess(expression)
    }

    override fun visitVararg(expression: IrVararg) {
        visitTypeRecursively(expression, expression.varargElementType)
        visitExpression(expression)
    }

    override fun visitSpreadElement(spread: IrSpreadElement) {
        visitElement(spread)
    }

    override fun visitWhen(expression: IrWhen) {
        visitExpression(expression)
    }

    override fun visitBranch(branch: IrBranch) {
        visitElement(branch)
    }

    override fun visitElseBranch(branch: IrElseBranch) {
        visitBranch(branch)
    }
}
